#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

bool val[1010][1010] = { 0 };
int kp[1010][1010];
int length[1010][1010];
int my_max = 0;
int dx[4] = { 0,0,1,-1 };
int dy[4] = { 1,-1,0,0 };
int n, m;

void kps(int i, int j)
{
    memset(val, 0, sizeof(val));
    memset(length, 0, sizeof(length));
    queue<pair<int, int>> q;
    val[i][j] = 1;
    q.push({ i,j });
    while (!q.empty())
    {
        int x = q.front().first;
        int y = q.front().second;
        val[x][y] = 1;
        q.pop();
        for (int l = 0; l < 4; l++)
        {
            int x1 = x + dx[l];
            int y1 = y + dy[l];
            if (x1 >= 0 && x1 < n && y1 >= 0 && y1<m && !val[x1][y1] && kp[x][y]>kp[x1][y1])
            {
                length[x1][y1] = max(length[x1][y1], length[x][y] + 1);
                my_max = max(my_max, length[x1][y1]);
                q.push({ x1,y1 });
            }
        }
    }
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> kp[i][j];
        }
    }
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            kps(i, j);
        }
    }
    cout << my_max << endl;
    return 0;
}
//const int N = 11;
//bool dp[11];
//int arr[N];
//int n;
//int ret = 0;
//void dfs(int pos)
//{
//	if (pos == n + 1)
//	{
//		ret++;
//		return;
//	}
//	for (int i = 1; i <= n; i++)
//	{
//		if (dp[i])
//		{
//			continue;
//		}
//		if (dp[arr[i]])
//		{
//			return;
//		}
//		dp[i] = true;
//		dfs(pos + 1);
//		dp[i] = false;
//	}
//}
//int main()
//{
//	cin >> n;
//	for (int i = 1; i <= n; i++)
//	{
//		cin>>arr[i];
//	}
//	return 0;
//}
//
//struct TreeNode
//{
//	int _val;
//	TreeNode* _left;
//	TreeNode* _right;
//	TreeNode(int val):_val(val),_left(nullptr),_right(nullptr)
//	{}
//};
//
//int ret = -1110;
//int dfs(TreeNode* root)
//{
//	if (root == nullptr)
//	{
//		return 0;
//	}
//	int l = max(0, dfs(root->_left));
//	int r = max(0, dfs(root->_right));
//	ret = max(ret, l + r + root->_val);
//	return max(l, r) + root->_val;
//}
//
//
//const int N = 1e5 + 10;
//int n;
//int arr[N];
//
//int main()
//{
//	cin >> n;
//	for (int i = 0; i < n; i++)
//	{
//		cin >> arr[i];
//	}
//	int ret = 0;
//	int i = 0;
//	while (i < n)
//	{
//		if (i == n - 1)
//		{
//			ret++;
//			break;
//		}
//		if (arr[i] < arr[i + 1])
//		{
//			while (i + 1 < n && arr[i] <= arr[i + 1])
//			{
//				i++;
//			}
//			ret++;
//		}
//		else if (arr[i] > arr[i + 1])
//		{
//			while (i + 1 < n && arr[i] >= arr[i + 1])
//			{
//				i++;
//			}
//			ret++;
//		}
//		else
//		{
//			while (i + 1 < n && arr[i + 1] == arr[i + 1])
//			{
//				i++;
//			}
//		}
//		i++;
//	}
//	cout << ret << endl;
//	return 0;
//}
//
